package com.mpgame.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.mpgame.common.proto.*;
import com.mpgame.common.utils.Log;
import com.mpgame.database.redis.model.UserTokenInfo;
import com.mpgame.database.redis.utils.PlayerOnlineUtil;
import com.mpgame.database.redis.utils.RedisUtil;
import com.mpgame.database.redis.utils.TokenUtil;
import com.mpgame.managers.SceneManager;
import com.mpgame.common.helper.GrpcStreamHelper;

import io.grpc.stub.StreamObserver;

public class GameSvc extends GameServerServiceGrpc.GameServerServiceImplBase {

    private volatile GrpcStreamHelper streamHelper;
    @Override
    public StreamObserver<StreamPacket> gameStream(StreamObserver<StreamPacket> rspObs) {
        streamHelper = new GrpcStreamHelper(rspObs);
        Log.info("GameServer 建立新的流连接");
        return new StreamObserver<StreamPacket>() {
            @Override
            public void onNext(StreamPacket pkt) {
                try {
                    handleStreamPkt(pkt);
                } catch (Exception e) {
                    Log.err("处理流异常：" + e.getMessage());
                }
            }

            @Override
            public void onError(Throwable t) {
                Log.err("GameServer 流连接错误：" + t.getMessage());
                streamHelper.setObs(null);
            }

            @Override
            public void onCompleted() {
                Log.info("GameServer 流连接完成");
                streamHelper.setObs(null);
            }
        };
    }
    private void handleStreamPkt(StreamPacket pkt) {
        switch (pkt.getCmd()) {
            case GAME_MOVE_TO_REQ:
                handleGameMoveToReqStr(pkt);
                break;
            case GAME_CHAT_REQ:
                handleGameChatStr(pkt);
                break;
            case GAME_SWITCH_SCENE_REQ:
                handleGameSwitchSceneStr(pkt);
                break;
            default:
                Log.warn("GameSvc流式消息不处理消息：" + pkt.getCmd());
                break;
        }
    }
    @Override
    public void getInitData(GameInitDataReq req, StreamObserver<GameInitDataRsp> rspObs) {
        List<UserTokenInfo> utis = PlayerOnlineUtil.getAllOnlinePlayerInfos();

        GameInitDataRsp.Builder rsp = GameInitDataRsp.newBuilder();

        for (UserTokenInfo uti : utis) {
            rsp.addUtis(
                    UserTokenInfoRsp.newBuilder()
                            .setAccountId(uti.getAccountId())
                            .setUsername(uti.getUsername())
                            .setNickname(uti.getNickname())
                            .setToken(uti.getToken())
                            .setLastLoginTs(uti.getLastLoginTimestamp())
                            .setLastActiveTs(uti.getLastActiveTimestamp())
                            .setPosX(uti.getPosX())
                            .setPosY(uti.getPosY())
                            .setSceneId(uti.getSceneId())
                            .build());
        }
        rspObs.onNext(rsp.build());
        rspObs.onCompleted();
    }
    private void handleGameMoveToReqStr(StreamPacket pkt) {
        try {
            GameMoveToReq req = GameMoveToReq.parseFrom(pkt.getData());
            GameMoveToRsp rsp = GameMoveToRsp.newBuilder()
                    .setTargetPosX(req.getTargetPosX())
                    .setTargetPosY(req.getTargetPosY())
                    .setAccountId(req.getAccountId())
                    .build();

            String sessionKey = TokenUtil.getSessionPrefix(req.getAccountId());
            Map<String, String> pData = new HashMap<>();
            pData.put("posX", String.valueOf(req.getTargetPosX()));
            pData.put("posY", String.valueOf(req.getTargetPosY()));
            RedisUtil.hmset(sessionKey, pData);

            List<Integer> targets = new ArrayList<>();
            for (UserTokenInfo uti : PlayerOnlineUtil.getAllOnlinePlayerInfos())
                if (uti.getAccountId() != req.getAccountId())
                    targets.add(uti.getAccountId());
            streamHelper.sendStreamPkt(targets, CmdId.GAME_MOVE_TO_RSP, rsp);
        } catch (Exception e) {
            Log.err("玩家移动消息处理失败：" + e.getMessage());
        }

    }
    private void handleGameChatStr(StreamPacket pkt) {
        try {
            Log.info("处理玩家聊天消息：" + pkt);
            GameChatReq req = GameChatReq.parseFrom(pkt.getData());
            GameChatRsp rsp = GameChatRsp.newBuilder()
                    .setAccountId(req.getAccountId())
                    .setContent(req.getContent())
                    .build();

            List<Integer> targets = new ArrayList<>();
            for (UserTokenInfo uti : PlayerOnlineUtil.getAllOnlinePlayerInfos())
                if (uti.getAccountId() != req.getAccountId())
                    targets.add(uti.getAccountId());
            streamHelper.sendStreamPkt(targets, CmdId.GAME_CHAT_RSP, rsp);
        } catch (Exception e) {
            Log.err("玩家聊天消息处理失败：" + e.getMessage());
        }
    }
    private void handleGameSwitchSceneStr(StreamPacket pkt){
        try{
            Log.info("处理玩家切换场景消息：" + pkt);
            GameSwitchSceneReq req = GameSwitchSceneReq.parseFrom(pkt.getData());
            boolean isSuccess = SceneManager.getInstance().enterScene(req.getAccountId(), req.getSceneName());
            if(isSuccess){
                
            }else{
                streamHelper.sendErrStreamPkt(req.getAccountId(), null, null);
            }
        }catch(Exception e){
            Log.err("玩家切换场景消息处理失败：" + e.getMessage());
        }
    }
}
